package org.theSeed.webFlux.filter;

import lombok.extern.slf4j.Slf4j;
import org.springframework.core.Ordered;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import org.theSeed.base.pojo.constant.SysConstant;
import org.theSeed.webFlux.sysEnum.FilterOrder;
import reactor.core.publisher.Mono;

import java.util.function.Supplier;

/**
 * 请求信息日志过滤器
 */
@Slf4j
public class ReqAndResLogFilter implements WebFilter, Ordered {
    public ReqAndResLogFilter() {
    }

    public ReqAndResLogFilter(Integer orderNum) {
        this.orderNum = orderNum;
    }

    public ReqAndResLogFilter(Supplier<Boolean> logFlagSupplier) {
        this.logFlagSupplier = logFlagSupplier;
    }

    public ReqAndResLogFilter(Integer orderNum, Supplier<Boolean> logFlagSupplier) {
        this.orderNum = orderNum;
        this.logFlagSupplier = logFlagSupplier;
    }

    protected Integer orderNum = FilterOrder.REQUEST_LOG.getCode();

    /**
     * 开启请求日志记录标识
     */
    protected Supplier<Boolean> logFlagSupplier = ()->{return true;};

    @Override
    public int getOrder() {
        return orderNum;
    }

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
        Boolean logFlag = logFlagSupplier.get();
        if (logFlag){
            //请求体处理
            ServerHttpRequest serverHttpRequest = exchange.getRequest();
            String pathInfo = serverHttpRequest.getURI().getPath();
            if (logFlag){
                if (serverHttpRequest instanceof RepeatReadFilter.CachedBodyHttpRequestWrapper){
                    ((RepeatReadFilter.CachedBodyHttpRequestWrapper)serverHttpRequest).getCachedBody()
                            .defaultIfEmpty(exchange.getResponse().bufferFactory().wrap("".getBytes(SysConstant.defaultCharset)))
                            .doOnNext(ele->{
                                log.info("请求路径:{},请求参数{}",pathInfo,ele.toString(SysConstant.defaultCharset));
                            })
                            .subscribe();
                }else{
                    log.error("日志过滤器请求信息不支持");
                }
            }

            return chain.filter(exchange)
                    .doOnSuccess(ele->{
                        if (logFlag){
                            ServerHttpResponse serverHttpResponse = exchange.getResponse();
                            if (serverHttpResponse instanceof RepeatReadFilter.CachedBodyHttpResponseWrapper){
                                Mono.just(((RepeatReadFilter.CachedBodyHttpResponseWrapper)serverHttpResponse).getCachedBody())
                                        .defaultIfEmpty("")
                                        .doOnNext(sonEle->{
                                            log.info("请求路径:{},响应结果{}",pathInfo,sonEle);
                                        })
                                        .subscribe();
                            }else{
                                log.error("日志过滤器响应信息不支持");
                            }
                        }
                    });
        }else{
            return chain.filter(exchange);
        }
    }
}
